package cn.yx.framework.util;

/**
 * @author ZHUL
 * @version V1.0
 * @Title: ${file_name}
 * @Package ${package_name}
 * @Description: ${todo}
 * @date 2017-02-16 13:35
 */
public class HexUtil {
    private static final char[] DIGITS_LOWER = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    private static final char[] DIGITS_UPPER = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    public HexUtil() {
    }

    public static char[] bytes2Hex(byte[] data) {
        return bytes2Hex(data, true);
    }

    public static char[] bytes2Hex(byte[] data, boolean uppercase) {
        return bytes2Hex(data, uppercase?DIGITS_UPPER:DIGITS_LOWER);
    }

    public static String bytes2HexStr(byte[] data) {
        return bytes2HexStr(data, true);
    }

    public static String bytes2HexStr(byte[] data, boolean uppercase) {
        return bytes2HexStr(data, uppercase?DIGITS_UPPER:DIGITS_LOWER);
    }

    public static byte[] hexChar2Byte(char[] data) {
        int len = data.length;
        if((len & 1) != 0) {
            throw new RuntimeException("Odd number of characters.");
        } else {
            byte[] out = new byte[len >> 1];
            int i = 0;

            for(int j = 0; j < len; ++i) {
                int f = char2Int(data[j], j) << 4;
                ++j;
                f |= char2Int(data[j], j);
                ++j;
                out[i] = (byte)(f & 255);
            }

            return out;
        }
    }

    public static int char2Int(char ch, int index) {
        int digit = Character.digit(ch, 16);
        if(digit == -1) {
            throw new RuntimeException("Illegal hexadecimal character " + ch + " at index " + index);
        } else {
            return digit;
        }
    }

    private static String bytes2HexStr(byte[] data, char[] toDigits) {
        return new String(bytes2Hex(data, toDigits));
    }

    private static char[] bytes2Hex(byte[] data, char[] toDigits) {
        int len = data.length;
        char[] out = new char[len << 1];
        int i = 0;

        for(int j = 0; i < len; ++i) {
            out[j++] = toDigits[(240 & data[i]) >>> 4];
            out[j++] = toDigits[15 & data[i]];
        }

        return out;
    }
}